﻿using System;
using System.Collections.Generic;
using System.Linq;
using Loki.Engine;
using Luna.Data.Project;
using NUnit.Framework;

namespace Luna.Data.Tests
{
    public class ProjectTaskTest : AssertionHelper
    {
        public IProjectData Project { get; set; }

        public IProjectTaskData Task1 { get; set; }
        public IProjectTaskData Task2 { get; set; }
        public IProjectTaskData Task3 { get; set; }

        private bool AreSame(IProjectTaskData P_Cat1, IProjectTaskData P_Cat2)
        {
            bool b = true;
            b &= P_Cat1.Budget == P_Cat1.Budget;
            b &= P_Cat1.Code == P_Cat2.Code;
            b &= P_Cat1.End == P_Cat2.End;
            b &= P_Cat1.PK == P_Cat2.PK;
            b &= P_Cat1.ProjectID == P_Cat2.ProjectID;
            b &= P_Cat1.Start == P_Cat2.Start;
            b &= P_Cat1.Name == P_Cat2.Name;
            return b;
        }

        public IProjectDataProvider Data { get; set; }

        private IProjectData CreateProject(string P_Name)
        {
            Random L_Rand = new Random(DateTime.Now.Millisecond);
            IProjectData L_Return = Data.Create<IProjectData>();
            L_Return.PK = Guid.NewGuid();
            L_Return.Code = P_Name + "_Code";
            L_Return.Name = P_Name + "_Name";
            L_Return.Description = P_Name + "_Description";
            L_Return.Budget = L_Rand.Next(1000) + 0.25m;
            return L_Return;
        }

        private IProjectTaskData Create(string P_Name, IProjectData P_Project)
        {
            Random L_Rand = new Random(DateTime.Now.Millisecond);
            IProjectTaskData L_Return = Data.Create<IProjectTaskData>();
            L_Return.PK = Guid.NewGuid();
            L_Return.Code = P_Name + "_Code";
            L_Return.Name = P_Name + "_Name";
            L_Return.ProjectID = P_Project.PK;
            L_Return.Start = DateTime.Today.AddDays(L_Rand.Next(20));
            L_Return.End = DateTime.Today.AddDays(L_Rand.Next(10));
            L_Return.Budget = L_Rand.Next(1000) + 0.25m;
            return L_Return;
        }

        [SetUp]
        public void SetUp()
        {
            Data = ContextHelper.GetDataModel<LunaDataModel>().Project;

            Project = CreateProject("Project1");

            Task1 = Create("Task1", Project);
            Task2 = Create("Task2", Project);
            Task3 = Create("Task3", Project);

            CleanTable();
        }

        [TearDown]
        public void CleanTable()
        {
            IEnumerable<IProjectTaskData> L_Categories = Data.GetAllTasks();
            foreach (var L_Cat in L_Categories)
            {
                Data.DeleteTask(L_Cat.PK);
            }

            foreach (var L_Cat in L_Categories)
            {
                Data.DeleteProject(L_Cat.ProjectID);
            }
        }

        [Test]
        public void TestGetAllByProject()
        {
            Data.SaveProject(Project, new IProjectTaskData[] { });

            Data.SaveTask(Task1);

            IEnumerable<IProjectTaskData> L_Operations = Data.GetAllTasksByProject(Project.PK);
            Expect(L_Operations.Count(), EqualTo(1));
        }

        [Test]
        public void TestInsertAndGet()
        {
            Data.SaveProject(Project, new IProjectTaskData[] { });

            Data.SaveTask(Task1);
            IProjectTaskData L_Operation = Data.GetTask(Task1.PK);
            Expect(AreSame(Task1, L_Operation), Is.True);
        }

        [Test]
        public void TestUpdateAndGet()
        {
            Data.SaveProject(Project, new IProjectTaskData[] { });

            Data.SaveTask(Task1);
            Task1.Name = "Operation1_Name_Modified";
            Data.SaveTask(Task1);

            IProjectTaskData L_Operation = Data.GetTask(Task1.PK);
            Expect(AreSame(Task1, L_Operation), Is.True);

            Expect(L_Operation.Name, Is.EqualTo("Operation1_Name_Modified"));
        }

        [Test]
        public void TestInsertAndGetAll()
        {
            Data.SaveProject(Project, new IProjectTaskData[] { });

            Data.SaveTask(Task1);
            Data.SaveTask(Task2);
            Data.SaveTask(Task3);

            int L_Count = Data.GetAllTasks().Count();
            Expect(L_Count, Is.EqualTo(3));
        }

        [Test]
        public void TestInsertAndDelete()
        {
            Data.SaveProject(Project, new IProjectTaskData[] { });

            Data.SaveTask(Task1);
            Data.SaveTask(Task2);
            Data.DeleteTask(Task1.PK);

            int L_Count = Data.GetAllTasks().Count();
            Expect(L_Count, Is.EqualTo(1));
            IProjectTaskData L_Operation = Data.GetTask(Task1.PK);
            Expect(L_Operation, Is.Null);

        }

        [Test]
        public void TestNoRef()
        {
            Expect(() => Data.SaveTask(Task1), Throws.Exception);
        }
    }
}
